#ifndef PWRPLANT_H
#define PWRPLANT_H

#include <string>
#include <vector>
#include <list>

#include "Physical/property.h"
#include "Physical/generator.h"
#include "Physical/subStation.h"

/**
  * class pwrPlant
  * Base class of power plant. Currently loosely modeled on a traditional themal
  * power station.
  */

namespace physical
{

//class subStation;

class pwrPlant : protected property
{
public:         // Constructors/Destructors

    /**
     * Empty Constructor
     */
    pwrPlant ( );

    /**
     * Constructor including fuelCost (should be used)
     */
    pwrPlant (float cost );

    /**
     * Constructor including fuelCost (should be used)
     */
    pwrPlant (float cost, double lattitude, double longitude );

    /**
     * Empty Destructor
     */
    virtual ~pwrPlant ( );



public:         // Public general methods

    /**
     * Add generator to the plant from a generator object. Returns FALSE if error
     * occured, else returns TRUE.
     * Add a Generator object to the m_generatorVector List.
     * @return bool
     * @param  gen Generator object to be added to plant.
     */
    bool addGenerator ( generator* add_object = NULL );

    /**
     * Remove generator from the plant from a generator object. Returns FALSE if error
     * occured, else returns TRUE.
     * Remove a Generator object from m_generatorVector List
     * @return bool
     * @param  gen
     */
    bool removeGenerator ( generator* remove_object = NULL );

    /**
     * Get the list of Generator objects held by m_generatorVector
     * @return vector<generator*> list of Generator objects held by m_generatorVector
     */
    std::vector<generator*> getGeneratorList ( );

    /**
     * Returns the maximum electrical generation output of the plant.
     * @return float
     */
    float getMaxElectOutput ( );

    /**
     * Returns the minimum electrical generation output of the plant.
     * @return float
     */
    float getMinElectOutput ( );

    /**
     * Modify the power plants electrical output. Returns TRUE if sucessful, else
     * returns FALSE (i.e. requested output out of range).
     * @return bool
     * @param  electOutput Electrical output of the power plant.
     */
    bool setPlantOutput (double electOutput = -1.00 );

    /**
     * Connect power plant to substation (creates pointer from power plant to
     * substation object). Returns TRUE if successful, else FALSE.
     * @return bool
     * @param  subStation Pointer to substation object.
     */
    bool connectStation (property* substation = NULL );

    /**
     * Disconnects power plant to substation (destroys pointer from power plant to
     * substation object). Returns TRUE if successful, else FALSE.
     * @return bool
     * @param  subStation Pointer to substation object.
     */
    bool disconnectStation ( );

    /**
     * Print all information about power plant including all generators. Returns TRUE
     * if successfull, else FALSE.
     * @return bool
     */
    bool printPlantInfo ( );


protected:      // Protected methods

    /**
     * Remove generator from the plant from a generator object. Returns FALSE if error
     * occured, else returns TRUE. INTERNAL USE ONLY.
     * @return bool
     * @param  gen Plant generator number.
     */
    bool removeGen (int gen = -1 );

    /**
     * Remove generator from the plant from a generator object. Returns FALSE if error
     * occured, else returns TRUE. INTERNAL USE ONLY.
     * @return bool
     * @param  gen Plant generator number.
     */
    bool setGenON (int gen = -1 );

    /**
     * Begin generator shutdown sequence for generator number #'gen'. Returns FALSE if
     * error occured, else returns TRUE. INTERNAL USE ONLY.
     * @return bool
     * @param  gen Plant generator number.
     */
    bool setGenOFF (int gen = -1 );

    /**
     * Schedule output of all operational generators in plant.
     * @return double
     * @param  output generator output value.
     */
    double schedGenOutput (double output = -1.00 );


private:        // Private attribute accessor methods

    /**
     * Set the value of fuelCost
     * Monetary value of fuel used for power generation.
     * @param new_var the new value of fuelCost
     */
    void setFuelCost ( float new_var );

    /**
     * Get the value of fuelCost
     * Monetary value of fuel used for power generation.
     * @return the value of fuelCost
     */
    float getFuelCost ( );

    /**
     * Set the value of incrementalCost
     * List of incremental cost function constants for each generator.
     * @param new_var the new value of incrementalCost
     */
    void setIncrementalCost ( float** new_var );

    /**
     * Get the value of incrementalCost
     * List of incremental cost function constants for each generator.
     * @return the value of incrementalCost
     */
    float** getIncrementalCost ( );

    /**
     * Set the value of cost
     * List of cost function constants for each generator.
     * @param new_var the new value of cost
     */
    void setCost ( float** new_var );

    /**
     * Get the value of cost
     * List of cost function constants for each generator.
     * @return the value of cost
     */
    float** getCost ( );

    /**
     * Set the value of isPlantOperating
     * If any of the generators are operating then this is TRUE, else FALSE.
     * @param new_var the new value of isPlantOperating
     */
    void setIsPlantOperating ( bool new_var );

    /**
     * Get the value of isPlantOperating
     * If any of the generators are operating then this is TRUE, else FALSE.
     * @return the value of isPlantOperating
     */
    bool getIsPlantOperating ( );

    /**
     * Set the value of electOutput
     * Sum of electrical output from all generators in the power plant.
     * @param new_var the new value of electOutput
     */
    void setElectOutput ( double new_var );

    /**
     * Get the value of electOutput
     * Sum of electrical output from all generators in the power plant.
     * @return the value of electOutput
     */
    double getElectOutput ( );

    /**
     * Set the value of numElectGens
     * @param new_var the new value of numElectGens
     */
    void setNumElectGens ( int new_var );

    /**
     * Increment the value of numElectGens by one
     */
    void incrementNumElectGens ( );

    /**
     * Decrement the value of numElectGens by one
     */
    void decrementNumElectGens ( );

    /**
     * Get the value of numElectGens
     * @return the value of numElectGens
     */
    int getNumElectGens ( );

    /**
     * Set the value of subStation
     * Pointer to substation object connecting to the rest of the regional network.
     * @param new_var the new value of subStation
     */
    void setSubStation ( property* new_var );

    /**
     * Get the value of subStation
     * Pointer to substation object connecting to the rest of the regional network.
     * @return the value of subStation
     */
    property* getSubStation ( );

    /**
     * Set the value of uniquePlantID
     * Unique power plant ID. Cannot be modified after instance is created.
     * @param new_var the new value of uniquePlantID
     */
    void setUniquePlantID ( unsigned long new_var );

    /**
     * Get the value of uniquePlantID
     * Unique power plant ID. Cannot be modified after instance is created.
     * @return the value of uniquePlantID
     */
    unsigned long getUniquePlantID ( );

    /**
     * Get the value of POWER_PLANT_COUNT
     * Count of all power plants in the simulation. Only power plant constructors can
     * increment this variable. Nothing can devrement it. The result is a running count
     * of all power plants in the program instance.
     * @return the value of POWER_PLANT_COUNT
     */
    unsigned long getPOWER_PLANT_COUNT ( );

    void initAttributes ( ) ;


private:        // Static Private attributes

    static unsigned long POWER_PLANT_COUNT;// Count of all power plants in the simulation.
                                // Only power plant constructors can increment this variable. Nothing can decrement it.
                                // The result is a running count of all power plants in the program instance.


private:        // Private attributes

    float fuelCost;             // Monetary value of fuel used for power generation.
    std::vector<float*> incrementalCost;// List of incremental cost function constants for each generator.
    std::vector<float*> cost;           // List of cost function constants for each generator.
    bool isPlantOperating;      // If any of the generators are operating then this is TRUE, else FALSE.
    double electOutput;         // Sum of electrical output from all generators in the power plant.
    int numElectGens;           // Number of electric generators established in the plant
    std::vector<generator*> generatorVector;// List of generators in the power plant.
    property* subStationLink; // Pointer to substation object connecting to the rest of the regional network.
    unsigned long uniquePlantID;// Unique power plant ID. Cannot be modified after instance is created.

};

}; // end namespace physical

#endif // PWRPLANT_H
